package com.sdy.dcsb.web.controller;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sdy.common.model.Response;
import com.sdy.common.model.Result;
import com.sdy.dcsb.api.DcsbApi;
import com.sdy.dcsb.biz.model.EsbConsumerSystem;
import com.sdy.dcsb.biz.model.EsbInboundMain;
import com.sdy.dcsb.biz.model.EsbLogSummaryJoint;
import com.sdy.dcsb.biz.service.EsbConsumerSystemService;
import com.sdy.dcsb.biz.service.EsbInboundMainService;
import com.sdy.dcsb.biz.service.EsbLogSummaryService;
import com.sdy.dcsb.web.util.SearchBrowserKeywordsUtil;
import com.sdy.mvc.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.springframework.util.StringUtils.isEmpty;

/**
 * <p>
 * 服务日志统计表，10分钟间隔 控制器
 * </p>
 *
 * @author fb
 * @since 2019/12/10
 */
@Slf4j
@Controller
@RequestMapping("/EsbLogSummary")
@Api(tags = "服务日志统计表(10min)相关接口")
public class EsbLogSummaryController extends BaseController {
    @Autowired
    private EsbLogSummaryService esbLogSummaryService;
    @Autowired
    private EsbConsumerSystemService esbConsumerSystemService;
    @Autowired
    private EsbInboundMainService esbInboundMainService;
    @Autowired
    private DcsbApi dcsbApi;

    /**
     * 消费者分析
     *
     * @param systemCode 消费者系统编码
     * @param startTime  开始时间
     * @param endTime    截止时间
     * @return
     */
    @GetMapping("/consumerAnalysis")
    @ResponseBody
    @ApiOperation("消费者分析")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "systemCode", value = "消费者系统编码"),
            @ApiImplicitParam(dataType = "String", name = "startTime", value = "开始时间,yyyy-MM-dd HH:mm:ss"),
            @ApiImplicitParam(dataType = "String", name = "endTime", value = "截止时间,yyyy-MM-dd HH:mm:ss"),
    })
    public Response consumerAnalysis(String systemCode, String startTime, String endTime) {
        Result<JSONObject> result = getConsumerAnalysis(systemCode, startTime, endTime);
        if(!result.getSuccess()) {
            return Response.error(result.getMessage());
        }else {
            return Response.success(result.getData());
        }
    }

    /**
     * 消费者分析excel下载
     *
     * @param systemCode 消费者系统编码
     * @param startTime  开始时间
     * @param endTime    截止时间
     * @return
     */
    @GetMapping("/consumerAnalysisDownload")
    @ResponseBody
    @ApiOperation("消费者分析excel下载")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "systemCode", value = "消费者系统编码"),
            @ApiImplicitParam(dataType = "String", name = "startTime", value = "开始时间,yyyy-MM-dd HH:mm:ss"),
            @ApiImplicitParam(dataType = "String", name = "endTime", value = "截止时间,yyyy-MM-dd HH:mm:ss"),
    })
    public Response consumerAnalysisDownload(HttpServletResponse response, HttpServletRequest request,
                                             String systemCode, String startTime, String endTime) {
        Result<JSONObject> result = getConsumerAnalysis(systemCode, startTime, endTime);
        if(!result.getSuccess()) {
            return Response.error(result.getMessage());
        }
        String systemName = result.getMessage();
        JSONObject objectData = result.getData();
        JSONArray arrayCurve = objectData.getJSONArray("curve");
        JSONArray arrayHistogram = objectData.getJSONArray("histogram");
        Result<Object> excelDataResult= getExcelData(arrayCurve, arrayHistogram, systemName, "的接口使用情况", request, response);
        if(!excelDataResult.getSuccess()) {
            return Response.error(excelDataResult.getMessage());
        }else {
            return Response.success(excelDataResult.getMessage());
        }
    }

    /**
     * 获取消费者分析结果
     * @param systemCode
     * @param startTime
     * @param endTime
     * @return
     */
    private Result<JSONObject> getConsumerAnalysis(String systemCode, String startTime, String endTime) {
        // 取数据
        if (isEmpty(systemCode) || isEmpty(startTime) || isEmpty(endTime)) {
            return new Result<JSONObject>(null, "请求参数不能为空", -1, false);
        }
        try {
            systemCode = URLDecoder.decode(systemCode, "utf-8");
            startTime = URLDecoder.decode(startTime, "utf-8");
            endTime = URLDecoder.decode(endTime, "utf-8");
        } catch (Exception e) {
            return new Result<JSONObject>(null, "参数解码失败", -1, false);
        }
        QueryWrapper<EsbConsumerSystem> esbConsumerSystemQueryWrapper = new QueryWrapper<>();
        esbConsumerSystemQueryWrapper.eq("system_code", systemCode);
        List<EsbConsumerSystem> esbConsumerSystemResult = esbConsumerSystemService.list(esbConsumerSystemQueryWrapper);
        if (esbConsumerSystemResult.size() == 0) {
            return new Result<JSONObject>(null, "请求的消费者系统编码有误，查询不存在", -1, false);
        }
        String systemName = esbConsumerSystemResult.get(0).getSystemName();
        if (startTime.equals(endTime)) {
            return new Result<JSONObject>(null, "起止时间不能相同", -1, false);
        }
        long startStamp = dateToStamp(startTime);
        long endStamp = dateToStamp(endTime);
        if (isEmpty(startStamp) || isEmpty(endStamp) || startStamp == -1 || endStamp == -1) {
            return new Result<JSONObject>(null, "时间传输格式有误", -1, false);
        }
        if (endStamp > (startStamp + 30 * 24 * 60 * 60 * 1000L)) {
            return new Result<JSONObject>(null, "时间间隔超过30天", -1, false);
        }
        // 创建数据结构
        JSONObject objectData = new JSONObject();
        JSONArray arrayHistogram = new JSONArray();
        // 获取柱状图数据
        List<EsbLogSummaryJoint> histogramResult = esbLogSummaryService.selectDetailServiceUsing(systemCode, startTime, endTime, ">=");
        for (int i = 0; i < histogramResult.size(); i++) {
            JSONObject objectHistogramData = new JSONObject();
            objectHistogramData.put("histogramName", histogramResult.get(i).getName());
            objectHistogramData.put("histogramCount", histogramResult.get(i).getNum());
            arrayHistogram.add(i, objectHistogramData);
        }
        objectData.put("histogram", arrayHistogram);
        // 获取曲线数据
        long timeInterval = endStamp - startStamp;
        long interval = -1L;
        if (timeInterval <= 24 * 60 * 60 * 1000L) {
            interval = 30 * 60 * 1000L;
        }
        if (timeInterval > 24 * 60 * 60 * 1000L && timeInterval <= 3 * 24 * 60 * 60 * 1000L) {
            interval = 2 * 60 * 60 * 1000L;
        }
        if (timeInterval > 3 * 24 * 60 * 60 * 1000L && timeInterval <= 7 * 24 * 60 * 60 * 1000L) {
            interval = 6 * 60 * 60 * 1000L;
        }
        if (timeInterval > 7 * 24 * 60 * 60 * 1000L && timeInterval <= 15 * 24 * 60 * 60 * 1000L) {
            interval = 12 * 60 * 60 * 1000L;
        }
        if (timeInterval > 15 * 24 * 60 * 60 * 1000L && timeInterval <= 30 * 24 * 60 * 60 * 1000L) {
            interval = 24 * 60 * 60 * 1000L;
        }
        String startTimeRound = startTime.substring(0, 14) + "00:00";
        String start = "";
        String end = "";
        Integer signEq = 1;
        long timeAdd = dateToStamp(startTimeRound) + interval;
        start = startTime;
        end = getEnd(startTime, startTimeRound, start, interval, timeAdd);

        JSONArray arrayCurve = new JSONArray();
        Integer cycles = 0;
        while (dateToStamp(end) <= dateToStamp(endTime)) {
            List<EsbLogSummaryJoint> curveResult;
            if (signEq == 1) {
                curveResult = esbLogSummaryService.selectDetailServiceUsing(systemCode, start, end, ">=");
                signEq = 0;
            } else {
                curveResult = esbLogSummaryService.selectDetailServiceUsing(systemCode, start, end, ">");
            }
            JSONArray arrayDetail = new JSONArray();
            Integer counts = 0;
            for (int i = 0; i < curveResult.size(); i++) {
                JSONObject objectDetailData = new JSONObject();
                objectDetailData.put("name", curveResult.get(i).getName());
                objectDetailData.put("count", curveResult.get(i).getNum());
                arrayDetail.add(i, objectDetailData);
                counts = counts + curveResult.get(i).getNum();
            }
            JSONObject objectCurveData = new JSONObject();
            objectCurveData.put("date", end);
            objectCurveData.put("num", counts);
            objectCurveData.put("detail", arrayDetail);
            arrayCurve.add(cycles, objectCurveData);
            cycles++;
            start = end;
            end = stampToDate((dateToStamp(end) + interval));
        }
        objectData.put("curve", arrayCurve);
        return new Result<JSONObject>(objectData, systemName, 0, true);
    }

    private String getEnd(String startTime, String startTimeRound, String start, long interval, long timeAdd) {
        String end = "";
        if (startTime.equals(startTimeRound)) {
            end = stampToDate((dateToStamp(start) + interval));
        } else {
            while (timeAdd <= dateToStamp(startTime)) {
                timeAdd = timeAdd + interval;
            }
            end = stampToDate(timeAdd);
        }
        return end;
    }

    private Result<Object> getExcelData(JSONArray arrayCurve, JSONArray arrayHistogram, String systemName, String message,
                                        HttpServletRequest request, HttpServletResponse response) {
        try{
            response.setContentType("text/html;charset=utf-8");
            String name = systemName + message;
            String excelName = name;
            boolean isMSIE = SearchBrowserKeywordsUtil.isMSBrowser(request);
            if (isMSIE) {
                /**
                 * IE、360兼容版浏览器的乱码问题解决
                 */
                name = URLEncoder.encode(name, "UTF-8");
            } else {
                /**
                 *万能乱码问题解决
                 */
                name = new String(name.getBytes("UTF-8"), "ISO-8859-1");
            }
            response.setHeader("Content-Disposition", "attachment; filename=" + name + ".xls");
            ServletOutputStream outputStream = response.getOutputStream();
            ExcelWriter writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLS, true);
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName(excelName);
            // 写入标题
            List<List<String>> head = new ArrayList<List<String>>();
            List<String> headCoulumn = new ArrayList<String>();
            headCoulumn.add(excelName);
            head.add(headCoulumn);
            Table table = new Table(1);
            table.setHead(head);
            List<List<Object>> data = new ArrayList<>();
            // 写入首行时间
            List<Object> title = new ArrayList<>();
            for (int i = 0; i <= arrayCurve.size(); i++) {
                if (i == 0) {
                    title.add("");
                } else {
                    title.add(arrayCurve.getJSONObject((i - 1)).getString("date"));
                }
            }
            data.add(title);
            // 写个每个接口使用次数
            for (int i = 0; i < arrayHistogram.size(); i++) {
                List<Object> item = new ArrayList<>();
                String itemName = arrayHistogram.getJSONObject(i).getString("histogramName");
                item.add(itemName);
                for (int j = 0; j < arrayCurve.size(); j++) {
                    if (arrayCurve.getJSONObject(j).getInteger("num") == 0) {
                        item.add(0);
                    } else {
                        Integer sign = 0;
                        for (int h = 0; h < arrayCurve.getJSONObject(j).getJSONArray("detail").size(); h++) {
                            if (itemName.equals(arrayCurve.getJSONObject(j).getJSONArray("detail").getJSONObject(h).getString("name"))) {
                                item.add(arrayCurve.getJSONObject(j).getJSONArray("detail").getJSONObject(h).getInteger("count"));
                                sign = 1;
                                break;
                            }
                        }
                        if (sign == 0) {
                            item.add(0);
                        }
                    }
                }
                data.add(item);
            }
            writer.write1(data, sheet, table);
            writer.finish();
            outputStream.flush();
            outputStream.close();
        }catch (Exception e) {
            String msg = "下载失败：" + e.getMessage();
            return new Result<Object>(null, msg, -1, false);
        }
        return new Result<Object>(null, "下载成功", 0, true);
    }

    /**
     * 服务分析
     *
     * @param expid            服务id
     * @param requestStartTime 请求开始时间
     * @param requestEndTime   请求截止时间
     * @return
     */
    @GetMapping("/selectServiceAnalysis")
    @ResponseBody
    @ApiOperation("服务分析查询接口")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "requestStartTime", value = "请求开始时间,yyyy-MM-dd HH:mm:ss"),
            @ApiImplicitParam(dataType = "String", name = "requestEndTime", value = "请求结束时间,yyyy-MM-dd HH:mm:ss"),
            @ApiImplicitParam(dataType = "String", name = "expid", value = "服务id")
    })
    public Response selectServiceAnalysis(String expid, String requestStartTime, String requestEndTime) {
        Result<JSONObject> serviceAnalysis = getServive(expid, requestStartTime, requestEndTime);
        if (!serviceAnalysis.getSuccess()){
            return Response.error(serviceAnalysis.getMessage());
        }else {
            return Response.success(serviceAnalysis.getData());
        }
    }


    /**
     * 服务分析excel下载
     *
     * @param expid            服务id
     * @param requestStartTime 开始时间
     * @param requestEndTime   截止时间
     * @return
     */
    @GetMapping("/serviceAnalysisDownload")
    @ResponseBody
    @ApiOperation("服务分析excel下载")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "expid", value = "服务id"),
            @ApiImplicitParam(dataType = "String", name = "requestStartTime", value = "开始时间,yyyy-MM-dd HH:mm:ss"),
            @ApiImplicitParam(dataType = "String", name = "requestEndTime", value = "截止时间,yyyy-MM-dd HH:mm:ss"),
    })
    public Response serviceAnalysisDownload(HttpServletResponse response, HttpServletRequest request,
                                            String expid, String requestStartTime, String requestEndTime) {
        Result<JSONObject> servive = getServive(expid, requestStartTime, requestEndTime);
        if (!servive.getSuccess()) {
            return Response.error(servive.getMessage());
        }
        String servname = servive.getMessage();
        JSONArray histogram = servive.getData().getJSONArray("histogram");
        JSONArray curve = servive.getData().getJSONArray("curve");
        Result<Object> objectResult = getExcelData(curve, histogram, servname, "使用情况", request, response);
        if (objectResult.getSuccess()) {
            return Response.success(objectResult.getData());
        }else {
            return Response.error(objectResult.getMessage());
        }
    }

    /**
     * 获取服务分析数据
     * @param expid 服务id
     * @param requestStartTime 请求开始时间
     * @param requestEndTime 请求结束时间
     * @return
     */
    private Result<JSONObject> getServive(String expid, String requestStartTime, String requestEndTime) {
        if (isEmpty(expid) || isEmpty(requestStartTime) || isEmpty(requestEndTime)) {
            return new Result<JSONObject>(null, "请求参数不能为空", -1, false);
        }
        try {
            requestStartTime = URLDecoder.decode(requestStartTime, "utf-8");
            requestEndTime = URLDecoder.decode(requestEndTime, "utf-8");
        } catch (Exception e) {
            return new Result<JSONObject>(null, "参数解码失败", -1, false);
        }
        QueryWrapper<EsbInboundMain> esbInboundMainQueryWrapper = new QueryWrapper<>();
        esbInboundMainQueryWrapper.eq("serviceid", expid);
        List<EsbInboundMain> esbInboundMains = esbInboundMainService.list(esbInboundMainQueryWrapper);
        if (esbInboundMains.size() == 0) {
            return new Result<JSONObject>(null, "请求的服务id有误，查询不存在", -1, false);
        }
        String servname = esbInboundMains.get(0).getServname();
        if (requestStartTime.equals(requestEndTime)) {
            return new Result<JSONObject>(null, "请求时间不能相同", -1, false);
        }
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date startTime = dateFormat.parse(requestStartTime);
            Date endTime = dateFormat.parse(requestEndTime);
            int day = (int) (endTime.getTime() / 1000 / 24 / 3600 - startTime.getTime() / 1000 / 24 / 3600);
            if (day >= 30) {
                return new Result<JSONObject>(null, "时间间隔超过30天", -1, false);
            }

            JSONObject object = new JSONObject();
            JSONArray arrayHistogram = new JSONArray();
            //获取柱状图数据
            List<EsbLogSummaryJoint> histogramResult = esbLogSummaryService.selectEsbLogSummaries(expid, requestStartTime, requestEndTime, ">=");
            for (int i = 0; i < histogramResult.size(); i++) {
                JSONObject objectHistogramData = new JSONObject();
                objectHistogramData.put("histogramName", histogramResult.get(i).getConsumerName());
                objectHistogramData.put("histogramCount", histogramResult.get(i).getNum());
                arrayHistogram.add(i, objectHistogramData);
            }
            object.put("histogram", arrayHistogram);


            //获取曲线图数据
            long interval = -1L;
            if (day <= 1) {
                interval = 30 * 60 * 1000L;
            }
            if (day > 1 && day <= 3) {
                interval = 2 * 60 * 60 * 1000L;
            }
            if (day > 3 && day <= 7) {
                interval = 6 * 60 * 60 * 1000L;
            }
            if (day > 7 && day <= 15) {
                interval = 12 * 60 * 60 * 1000L;
            }
            if (day > 15 && day <= 30) {
                interval = 24 * 60 * 60 * 1000L;
            }
            String startTimeRound = requestStartTime.substring(0, 14) + "00:00";
            String start = "";
            String end = "";
            Integer signEq = 1;
            long timeAdd = dateToStamp(startTimeRound) + interval;

            start = requestStartTime;
            end = getEnd(requestStartTime, startTimeRound, start, interval, timeAdd);

            JSONArray arrayCurve = new JSONArray();
            Integer cycles = 0;
            while (dateToStamp(end) <= dateToStamp(requestEndTime)) {
                List<EsbLogSummaryJoint> curveResult;
                if (signEq == 1) {
                    curveResult = esbLogSummaryService.selectEsbLogSummaries(expid, start, end, ">=");
                    signEq = 0;
                } else {
                    curveResult = esbLogSummaryService.selectEsbLogSummaries(expid, start, end, ">");
                }
                JSONArray arrayDetail = new JSONArray();
                Integer counts = 0;
                for (int i = 0; i < curveResult.size(); i++) {
                    JSONObject objectDetailData = new JSONObject();
                    objectDetailData.put("name", curveResult.get(i).getConsumerName());
                    objectDetailData.put("count", curveResult.get(i).getNum());
                    arrayDetail.add(i, objectDetailData);
                    counts = counts + curveResult.get(i).getNum();
                }
                JSONObject objectCurveData = new JSONObject();
                objectCurveData.put("date", end);
                objectCurveData.put("num", counts);
                objectCurveData.put("detail", arrayDetail);
                arrayCurve.add(cycles, objectCurveData);
                cycles++;
                start = end;
                end = stampToDate((dateToStamp(end) + interval));
            }
            object.put("curve", arrayCurve);
            return new Result<JSONObject>(object, servname, 0, true);
        } catch (ParseException e) {
            log.info(e.getMessage());
        }
        return new Result<JSONObject>(null, "", 0, true);
    }

    private static long dateToStamp(String s) {
        String res = "";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        try {
            date = simpleDateFormat.parse(s);
        } catch (Exception e) {
            return -1;
        }
        long time = date.getTime();
        return time;
    }

    private static String stampToDate(long s) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = simpleDateFormat.format(new Date(s));
        return str;
    }

    /**
     * 自动在DCSB注册接口
     * @param interfaceName 接口名称
     * @param adapterType 适配类型，1:HTTP(默认选择),2:SOAP,3:WEBSERVICE,4:H5,5:微信小程序
     * @param contentType 请求头类型，1:multipart/form-data(默认选择),2:application/json,3:application/x-www-form-urlencoded,4:text/xml,5:application/xml
     * @param url 接口地址
     * @param httpType http的请求类型，1:GET,2:POST
     * @return
     */
    @GetMapping("/testRegisteredInterfaceAuthority")
    @ResponseBody
    @ApiOperation("测试自动注册接口功能，前端别用")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "interfaceName", value = "接口名称"),
            @ApiImplicitParam(dataType = "Integer", name = "adapterType", value = "适配类型，1:HTTP(默认选择),2:SOAP,3:WEBSERVICE,4:H5,5:微信小程序"),
            @ApiImplicitParam(dataType = "Integer", name = "contentType", value = "请求头类型，1:multipart/form-data(默认选择),2:application/json,3:application/x-www-form-urlencoded,4:text/xml,5:application/xml"),
            @ApiImplicitParam(dataType = "String", name = "url", value = "接口地址"),
            @ApiImplicitParam(dataType = "Integer", name = "httpType", value = "http的请求类型，1:GET,2:POST"),
    })
    public Response testRegisteredInterfaceAuthority(String interfaceName, Integer adapterType, Integer contentType, String url,
                                                     Integer httpType) {
        return dcsbApi.registeredInterfaceAuthority(interfaceName, adapterType, contentType, url, httpType);
    }

}
